﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using BlueLotus7.ArchiveSystem.Interfaces;
using System.Globalization;

namespace BlueLotus7.ArchiveSystem.Common
{
    [DataContract]
    public class DayTimeStatistics
    {
        protected const string defaultTimeFormat = "HH:mm";
        protected int[] timeArray;

        [DataContract]
        public enum GroupBys
        {
            [EnumMember]
            Quarter = 0,
            [EnumMember]
            HalfHour,
            [EnumMember]
            Hour,
            [EnumMember]
            WeekDay
        }

        [DataMember]
        public GroupBys GroupBy
        {
            get;
            set;
        }

        public int Length
        {
            get
            {
                return timeArray.Length;
            }
        }

        [DataMember]
        public int MaxRecordCount
        {
            get;
            set;
        }

        public DayTimeStatistics(GroupBys groupBy)
        {
            this.GroupBy = groupBy;
            switch (this.GroupBy)
            {
                case GroupBys.HalfHour:
                    timeArray = new int[48];
                    break;
                case GroupBys.Hour:
                    timeArray = new int[24];
                    break;
                case GroupBys.WeekDay:
                    timeArray = new int[7];
                    break;
                case GroupBys.Quarter:
                default:
                    timeArray = new int[96];
                    break;
            }
        }

        public int PlusOne(DateTime dateTime)
        {
            int index = GetIndexOfArray(dateTime);
            timeArray[index]++;
            return timeArray[index];
        }

        public int GetValueByIndex(int index)
        {
            return timeArray[index];
        }

        public string GetStartTimeMarkByIndex(int index)
        {
            return GetDayTimeMarkByIndex(index, null);
        }

        protected int GetIndexOfArray(DateTime stamp)
        {
            int result = -1;

            if (this.GroupBy == GroupBys.WeekDay)
            {
                result = (int)stamp.DayOfWeek;
            }
            else
            {
                int hourSplit = 1;
                switch (this.GroupBy)
                {
                    case GroupBys.HalfHour:
                        hourSplit = 2;
                        break;
                    case GroupBys.Hour:
                        hourSplit = 1;
                        break;
                    case GroupBys.Quarter:
                    default:
                        hourSplit = 4;
                        break;
                }

                int major = stamp.Hour * hourSplit;
                if (major > 0)
                {
                    major--;
                }
                decimal minutePart = stamp.Minute / (60 / hourSplit);
                int offset = (stamp.Minute == 0 ? 0 : (int)(minutePart));
                major += offset;
                if ((decimal)((int)minutePart) != minutePart)
                {
                    major++;
                }
            }

            return result;
        }

        protected string GetDayTimeMarkByIndex(int index, string format)
        {
            string result = string.Empty;

            if (this.GroupBy == GroupBys.WeekDay)
            {
                result = ((DayOfWeek)index).ToString();
            }
            else
            {
                if (format == null)
                {
                    format = defaultTimeFormat;
                }

                int hourSplit = 1;
                switch (this.GroupBy)
                {
                    case GroupBys.HalfHour:
                        hourSplit = 2;
                        break;
                    case GroupBys.Hour:
                        hourSplit = 1;
                        break;
                    case GroupBys.Quarter:
                    default:
                        hourSplit = 4;
                        break;
                }

                int hour, minute = 0;
                hour = (int)(index / hourSplit);
                minute = (index - hour) * (60 / hourSplit);

                result = (new DateTime(1986, 12, 01, hour, minute, 0)).ToString(format);
            }

            return result;
        }
    }
}
